use rubato::{Resampler, SincFixedOut, SincInterpolationParameters, SincInterpolationType, WindowFunction};

pub struct HighQualityResampler {
    resampler: Option<SincFixedOut<f32>>,
    input_rate: u32,
    output_rate: u32,
    channels: usize,
    input_buffer: Vec<Vec<f32>>,
}

impl HighQualityResampler {
    pub fn new(input_rate: u32, output_rate: u32, channels: usize) -> Result<Self, Box<dyn std::error::Error>> {
        let resampler = if input_rate != output_rate {
            let params = SincInterpolationParameters {
                sinc_len: 128,
                f_cutoff: 0.95,
                interpolation: SincInterpolationType::Linear,
                oversampling_factor: 128,
                window: WindowFunction::BlackmanHarris2,
            };
            let output_frame_size = (output_rate * 20 / 1000) as usize;
            Some(SincFixedOut::<f32>::new(
                output_rate as f64 / input_rate as f64,
                2.0,
                params,
                output_frame_size,
                channels,
            )?)
        } else { None };
        Ok(Self { resampler, input_rate, output_rate, channels, input_buffer: vec![Vec::new(); channels] })
    }

    pub fn process(&mut self, input: &[f32]) -> Result<Vec<f32>, Box<dyn std::error::Error>> {
        if let Some(ref mut resampler) = self.resampler {
            let frames = input.len() / self.channels;
            for frame in 0..frames { for ch in 0..self.channels { self.input_buffer[ch].push(input[frame * self.channels + ch]); } }
            let mut output = Vec::new();
            while !self.input_buffer[0].is_empty() {
                let needed_input = resampler.input_frames_next();
                if self.input_buffer[0].len() >= needed_input {
                    let mut input_chunk = Vec::with_capacity(self.channels);
                    for ch in 0..self.channels { let chunk: Vec<f32> = self.input_buffer[ch].drain(0..needed_input).collect(); input_chunk.push(chunk); }
                    match resampler.process(&input_chunk, None) {
                        Ok(output_chunk) => {
                            let output_frames = output_chunk[0].len();
                            for frame in 0..output_frames { for ch in 0..self.channels { output.push(output_chunk[ch][frame]); } }
                        }
                        Err(e) => { for ch in 0..self.channels { self.input_buffer[ch].clear(); } return Err(format!("重采样失败: {}", e).into()); }
                    }
                } else { break; }
            }
            Ok(output)
        } else { Ok(input.to_vec()) }
    }
}


